package ca.seia.comp6521.a1.externalmergesort;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import ca.seia.comp6521.a1.io.DataFileWriter;
import ca.seia.comp6521.a1.util.MemoryCalculator;

public class PhaseIExecutioner {

	private static final String SUBLIST_FILE_PREFIX = "phase1SortedSublist";
	private static final String FILE_EXT = ".dat";
	
	private String subListDirectory;
	private String filePath;
	private int memoryBufferInMB;
	private long totalSortTime;
	private long totalWriteTime;
	private DataFileWriter writer;
	
	
	public PhaseIExecutioner(String subListDirectory, String filePath,
			int memoryBufferInMB) {
		this(subListDirectory,filePath,memoryBufferInMB,new DataFileWriter());
	}
	
	public PhaseIExecutioner(String subListDirectory, String filePath,
			int memoryBufferInMB, DataFileWriter writer) {
		this.subListDirectory = subListDirectory;
		this.filePath = filePath;
		this.memoryBufferInMB = memoryBufferInMB;
		this.writer = writer;
	}

	public PhaseIStatistics executePhaseI() throws IOException {
		
		List<String> subListFilePaths = new ArrayList<String>();
		Reader reader = new FileReader(this.filePath);
		String subListFilePath = null; 
		String line = null;
		int totalIntegers = 0; 
		int numberCounter = 0;
		int subListCount = 1;
		
		long startTime = System.currentTimeMillis();
		try (BufferedReader br = new BufferedReader(reader)) {
			int size = MemoryCalculator.getNumberOfPrimitiveInt(memoryBufferInMB);
//			System.out.println("Number of Integers for " + memoryBufferInMB + " megs is " + size);
//			 Integer[] numbers = new Integer[size];
			int[] numbers = new int[size];
			while ((line = br.readLine()) != null) {
				numbers[numberCounter] = Integer.parseInt(line);
				totalIntegers++;
				if (numberCounter >= size - 1) {
					subListFilePath = generateAbsoluteFilePath(subListCount);
					sortAndWriteToDisk(subListFilePath, numbers);
					subListFilePaths.add(subListFilePath);
					subListCount++;
					numberCounter = -1;
				}
				numberCounter++;
			}
//			Processing for lastSubList
			flagUnusedValues(numbers,numberCounter);
			subListFilePath = generateAbsoluteFilePath(subListCount);
			sortAndWriteToDisk(subListFilePath, numbers);
			subListFilePaths.add(subListFilePath);
//			System.out.println("number of integers processed " + totalIntegers);
		}
		long executionTime = System.currentTimeMillis() - startTime;
		return new PhaseIStatistics(executionTime, totalSortTime, totalWriteTime,totalIntegers, subListFilePaths);
	}

	private void flagUnusedValues(int[] numbers,int indexToStartFlagging) {
		for(int i = indexToStartFlagging; i< numbers.length; i ++) 
			numbers[i] = -1;
	}
	
	private void flagUnusedValues(Integer[] numbers,int indexToStartFlagging) {
		for(int i = indexToStartFlagging; i< numbers.length; i ++) 
			numbers[i] = -1;
	}
	
	
	private void sortAndWriteToDisk(String subListFilePath,int[] numbers) throws IOException {
		long startTime = System.currentTimeMillis();
		Arrays.sort(numbers);
		long sortTime = System.currentTimeMillis() - startTime;
		totalSortTime += sortTime;
		
		long startWriteTime = System.currentTimeMillis();
		writer.writeFile(subListFilePath, numbers);
		long writeTime = System.currentTimeMillis() - startWriteTime;
		totalWriteTime += writeTime;
	}
	
	private void sortAndWriteToDisk(String subListFilePath,Integer[] numbers) throws IOException {
		long startTime = System.currentTimeMillis();
		Arrays.sort(numbers);
		long sortTime = System.currentTimeMillis() - startTime;
		totalSortTime += sortTime;
		
		long startWriteTime = System.currentTimeMillis();
		writer.writeFile(subListFilePath, numbers);
		long writeTime = System.currentTimeMillis() - startWriteTime;
		totalWriteTime += writeTime;
	}
	
	
	private String generateAbsoluteFilePath(int subListCount) {
		return subListDirectory + generateFileName(subListCount);
	}
	
	private String generateFileName(int subListCount) {
		return SUBLIST_FILE_PREFIX+subListCount+FILE_EXT;
	}

	public String getSubListDirectory() {
		return subListDirectory;
	}
	
	public void setSubListDirectory(String subListDirectory) {
		this.subListDirectory = subListDirectory;
	}
	
	public String getFilePath() {
		return filePath;
	}
	
	public void setFilePath(String filePath) {
		this.filePath = filePath;
	}
	
	public int getMemoryBufferInMB() {
		return memoryBufferInMB;
	}
	
	public void setMemoryBufferInMB(int memoryBufferInMB) {
		this.memoryBufferInMB = memoryBufferInMB;
	}

}
